/***************************************************************************
 *
 * Copyright (c) 2012 Baidu.com, Inc. All Rights Reserved
 * common.h,v 1.0 2012-08-17 11:30 yelu01
 *
 **************************************************************************/



/**
 * @file file_map.h
 * @author yelu01(yelu01@baidu.com)
 * @date 2012-08-17 11:30
 * @version 1.0
 * @brief matrix item.
 *
 **/

#pragma once

#include <boost/shared_ptr.hpp>
#include <cassert>
#include "bytes.h"

struct item_t
{
	item_t();
	bytes_t row;
	bytes_t col;
	uint64_t timestamp;
	bool del;
	bytes_t value;
	uint64_t size();
	uint64_t serialize(FILE* fp);
	uint64_t deserialize(FILE* fp);
};
typedef boost::shared_ptr<item_t> pitem;

// Comparator type for comparing keys.
typedef bool (*comparator)(const bytes_t&, const bytes_t&);

// Comparator for comparing items required by std::vector<item_t*>&.
// It is constructed based on use-specified cmp.
struct item_less_cmp
{
	item_less_cmp(comparator row_cmp, comparator col_cmp)
	{
		this->row_cmp = row_cmp;
		this->col_cmp = col_cmp;
	}
	bool operator() (const pitem& a, const pitem& b)
	{
		assert(a && b);
		// here, a != null && b != null;
		// If index_key is equal, cmp extra_key with raw_comparator.
		if(row_cmp(a->row, b->row)){ return true; }
		if(!row_cmp(b->row, a->row))
		{
			// here a.row == b.row.
			if(col_cmp(a->col, b->col)) {return true;}
			if(!col_cmp(b->col, a->col))
			{
				// here a.row == b.row, a.col == b.col.
				return a->timestamp > b->timestamp;
			}
			// here a.row == b.row, a.col > b.col.
			return false;
		}
		// here a.row > b.row.
		return false;
	}

	comparator row_cmp;
	comparator col_cmp;
};

struct item_eq_cmp
{
	item_eq_cmp(comparator row_cmp, comparator col_cmp)
	{
		this->row_cmp = row_cmp;
		this->col_cmp = col_cmp;
	}
	bool operator() (const pitem& a, const pitem& b)
	{
		assert(a && b);
		if(!row_cmp(a->row, b->row) &&
			!row_cmp(b->row, a->row) &&
			!col_cmp(a->col, b->col) &&
			!col_cmp(b->col, a->col))
		{ return true; }
		return false;
	}

	comparator row_cmp;
	comparator col_cmp;
};

struct item_ne_cmp
{
	item_ne_cmp(comparator row_cmp, comparator col_cmp)
	{
		this->row_cmp = row_cmp;
		this->col_cmp = col_cmp;
	}
	bool operator() (const pitem& a, const pitem& b)
	{
		assert(a && b);
		if(row_cmp(a->row, b->row) ||
			row_cmp(b->row, a->row) ||
			col_cmp(a->col, b->col) ||
			col_cmp(b->col, a->col))
		{ return true; }
		return false;
	}

	comparator row_cmp;
	comparator col_cmp;
};

struct row_eq_cmp
{
	row_eq_cmp(comparator less_cmp)
	{
		this->less_cmp = less_cmp;
	}
	bool operator()(const bytes_t& lhs, const bytes_t& rhs)
	{
		assert(lhs.size() != 0 && (void*)lhs != NULL &&
				rhs.size() != 0 && (void*)rhs != NULL);
		if(!less_cmp(lhs, rhs) && !less_cmp(rhs, lhs))
		{
			return true;
		}
		return false;
	}
	comparator less_cmp;
};

struct row_ne_cmp
{
	row_ne_cmp(comparator less_cmp)
	{
		this->less_cmp = less_cmp;
	}
	bool operator()(const bytes_t& lhs, const bytes_t& rhs)
	{
		assert(lhs.size() != 0 && (void*)lhs != NULL &&
						rhs.size() != 0 && (void*)rhs != NULL);
		if(less_cmp(lhs, rhs) || less_cmp(rhs, lhs))
		{
			return true;
		}
		return false;
	}
	comparator less_cmp;
};

